package cn.ynrcb.personnelfile.common.utils;

import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;

/**
 * 日期处理
 */
public class DateUtils {
    private static final long ONE_MINUTE = 60;
    private static final long ONE_HOUR = 3600;
    private static final long ONE_DAY = 86400;
    private static final long ONE_MONTH = 2592000;
    private static final long ONE_YEAR = 31104000;
    public final static char[] upper = "零一二三四五六七八九十".toCharArray();
    /**
     * 时间格式(yyyy-MM-dd)
     */
    public final static String DATE_PATTERN = "yyyy-MM-dd";
    public final static String DATE_PATTERN_YM = "yyyy-MM";
    /**
     * 时间格式(20191206)
     */
    public final static String DATE_PATTERN_NUM = "yyyyMMdd";
    public final static String DATE_PATTERN_NUM_YM = "yyyyMM";
    /**
     * 时间格式(2020/06/10)
     */
    public final static String DATE_PATTERN_CHAR = "yyyy/MM/dd";
    /**
     * 时间格式(yyyy-MM-dd HH:mm:ss)
     */
    public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

    /**
     * 日期格式化 日期格式为：yyyy-MM-dd
     *
     * @param date 日期
     * @return 返回yyyy-MM-dd格式日期
     */
    public static String format(Date date) {
        return format(date, DATE_PATTERN);
    }

    public static String formatUTC(String date) throws ParseException {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        df.setTimeZone(TimeZone.getTimeZone("UTC"));
        return df.parse(date).toString();
    }

    public static String formatToNumber(Date date) {
        return format(date, DATE_PATTERN_NUM);
    }

    public static String getFullDate() {
        SimpleDateFormat simple = new SimpleDateFormat(DATE_TIME_PATTERN);
        return simple.format(Calendar.getInstance().getTime());
    }

    /**
     * 日期格式化 日期格式为：yyyy-MM-dd
     *
     * @param date    日期
     * @param pattern 格式，如：DateUtils.DATE_TIME_PATTERN
     * @return 返回yyyy-MM-dd格式日期
     */
    public static String format(Date date, String pattern) {
        if (date != null) {
            SimpleDateFormat df = new SimpleDateFormat(pattern);
            return df.format(date);
        }
        return null;
    }

    /**
     * 字符串转换成日期
     *
     * @param strDate 日期字符串
     * @param pattern 日期的格式，如：DateUtils.DATE_TIME_PATTERN
     */
    public static Date stringToDate(String strDate, String pattern) {
        if (StringUtils.isBlank(strDate)) {
            return null;
        }

        DateTimeFormatter fmt = DateTimeFormat.forPattern(pattern);
        return fmt.parseLocalDateTime(strDate).toDate();
    }

    /**
     * 将Json转换过来的带T的字符串格式的时间转换成正常时间，并通过指定格式输出
     * Author：William（徐威）
     * Create Time：2018-08-07
     *
     * @param strDate 传入的json格式化转换而来的时间
     * @param fmt     要传出的时间格式
     * @return
     */
    public static String convertJsonDate(String strDate, String fmt) {
        String str = "";
        try {
            if (fmt == null || fmt.length() == 0) {
                fmt = "yyyy-MM-dd HH:mm:ss";
            }
            strDate = strDate.replace("T", " ");
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date dt = sdf.parse(strDate);

            sdf = new SimpleDateFormat(fmt);
            str = sdf.format(dt);
            return str;
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return str;
    }

    /**
     * 根据周数，获取开始日期、结束日期
     *
     * @param week 周期  0本周，-1上周，-2上上周，1下周，2下下周
     * @return 返回date[0]开始日期、date[1]结束日期
     */
    public static Date[] getWeekStartAndEnd(int week) {
        DateTime dateTime = new DateTime();
        LocalDate date = new LocalDate(dateTime.plusWeeks(week));

        date = date.dayOfWeek().withMinimumValue();
        Date beginDate = date.toDate();
        Date endDate = date.plusDays(6).toDate();
        return new Date[]{beginDate, endDate};
    }

    /**
     * 对日期的【秒】进行加/减
     *
     * @param date    日期
     * @param seconds 秒数，负数为减
     * @return 加/减几秒后的日期
     */
    public static Date addDateSeconds(Date date, int seconds) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusSeconds(seconds).toDate();
    }

    /**
     * 对日期的【分钟】进行加/减
     *
     * @param date    日期
     * @param minutes 分钟数，负数为减
     * @return 加/减几分钟后的日期
     */
    public static Date addDateMinutes(Date date, int minutes) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusMinutes(minutes).toDate();
    }

    /**
     * 对日期的【小时】进行加/减
     *
     * @param date  日期
     * @param hours 小时数，负数为减
     * @return 加/减几小时后的日期
     */
    public static Date addDateHours(Date date, int hours) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusHours(hours).toDate();
    }

    /**
     * 对日期的【天】进行加/减
     *
     * @param date 日期
     * @param days 天数，负数为减
     * @return 加/减几天后的日期
     */
    public static Date addDateDays(Date date, int days) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusDays(days).toDate();
    }

    /**
     * 对日期的【周】进行加/减
     *
     * @param date  日期
     * @param weeks 周数，负数为减
     * @return 加/减几周后的日期
     */
    public static Date addDateWeeks(Date date, int weeks) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusWeeks(weeks).toDate();
    }

    /**
     * 对日期的【月】进行加/减
     *
     * @param date   日期
     * @param months 月数，负数为减
     * @return 加/减几月后的日期
     */
    public static Date addDateMonths(Date date, int months) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusMonths(months).toDate();
    }

    /**
     * 对日期的【年】进行加/减
     *
     * @param date  日期
     * @param years 年数，负数为减
     * @return 加/减几年后的日期
     */
    public static Date addDateYears(Date date, int years) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusYears(years).toDate();
    }

    /**
     * 计算两个日期间相差多少天
     *
     * @param nowDateStr
     * @param endDateStr
     * @return
     */
    public static int daysDiff(String nowDateStr, String endDateStr) {
        int daydiff = 0;
        try {
            Calendar aCalendar = Calendar.getInstance();
            SimpleDateFormat sdf = new SimpleDateFormat(DATE_PATTERN);
            Date nowDate = sdf.parse(nowDateStr);
            aCalendar.setTime(nowDate);
            int day1 = aCalendar.get(Calendar.DAY_OF_YEAR);
            int year1 = aCalendar.get(Calendar.YEAR);

            Date endDate = sdf.parse(endDateStr);
            aCalendar.setTime(endDate);
            int day2 = aCalendar.get(Calendar.DAY_OF_YEAR);
            int year2 = aCalendar.get(Calendar.YEAR);
            if (year1 != year2)   //同一年
            {
                int timeDistance = 0;
                for (int i = year1; i < year2; i++) {
                    if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0)    //闰年
                    {
                        timeDistance += 366;
                    } else {
                        timeDistance += 365;
                    }
                }

                return timeDistance + (day2 - day1);
            } else {
                return day2 - day1;
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return daydiff;
    }

    /**
     * 比较两个日期间大小
     *
     * @param date_str1
     * @param date_str2
     * @return
     */
    public static boolean isBiggerDate(String date_str1, String date_str2) {
        if (date_str1 == null && date_str2 == null) {
            return true;
        } else if (date_str1 == null && date_str2 != null) {
            return false;
        } else if (date_str1 != null && date_str2 == null) {
            return true;
        }
        boolean isBigger = true;
        try {
            SimpleDateFormat df = new SimpleDateFormat(DATE_PATTERN);
            Date date1 = df.parse(date_str1);
            Date date2 = df.parse(date_str2);
            isBigger = date1.after(date2);//date_str1是否大于date_str2
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return isBigger;
    }

    /**
     * 结果为“0”是上午     结果为“1”是下午
     *
     * @return
     * @author swb
     * @version created at 2018年12月20日 上午10:06:56
     */
    public static int isAmOrPm() {
        GregorianCalendar ca = new GregorianCalendar();
        return ca.get(GregorianCalendar.AM_PM);
    }

    /**
     * @return yyyy-mm-dd
     * 2012-12-25
     */
    public static String getDate() {
        return getYear() + "-" + getMonth() + "-" + getDay();
    }

    /**
     * @param format
     * @return yyyy年MM月dd HH:mm
     * MM-dd HH:mm 2012-12-25
     */
    public static String getDate(String format) {
        SimpleDateFormat simple = new SimpleDateFormat(format);
        return simple.format(Calendar.getInstance().getTime());
    }

    public static String getDateYMD(int diff) {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, diff);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(cal.getTime());
    }

    public static String addDateYMD(Date currentDate, int day) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(currentDate);
        cal.add(Calendar.DATE, day); //把日期往后增加一天,整数  往后推,负数往前移动
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(cal.getTime()); //这个时间就是日期往后推一天的结果
    }

    public static String getTime() {
        Calendar cal = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
        return sdf.format(cal.getTime());
    }

    public static String getDateYMD(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(date);
    }


    public static String getDateYMD2(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        return sdf.format(date);
    }

    public static String getDateYMD3(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(date);
    }

    public static String getDateYMD4(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm");
        return sdf.format(date);
    }

    public static String getDateYMD5(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        return sdf.format(date);
    }

    public static String getChinaeseDateYMD(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
        return sdf.format(date);
    }

    public static String getChinaeseDateYMD(String date) {
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日");
        try {
            return sdf2.format(sdf1.parse(date));
        } catch (ParseException e) {
            e.printStackTrace();
            return date;
        }
    }

    public static String perseDate(String date, String format1, String format2) {
        SimpleDateFormat sdf1 = new SimpleDateFormat(format1);
        SimpleDateFormat sdf2 = new SimpleDateFormat(format2);
        try {
            return sdf2.format(sdf1.parse(date));
        } catch (ParseException e) {
            e.printStackTrace();
            return date;
        }
    }

    public static String nowToStamp() {
        Calendar calendar = Calendar.getInstance();
        long ts = calendar.getTime().getTime() / 1000;
        return String.valueOf(ts);
    }

    /**
     * @return yyyy-MM-dd HH:mm
     * 2012-12-29 23:47
     */
    public static String getDateAndMinute() {
        SimpleDateFormat simple = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        return simple.format(Calendar.getInstance().getTime());
    }

    public static String stampToDatestamp(String s) {
        String res;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        long lt = new Long(s);
        Date date = new Date(lt * 1000);
        res = simpleDateFormat.format(date);
        return res;
    }

    public static String strToDatestamp(String s) {
        Timestamp time = Timestamp.valueOf(s);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        return simpleDateFormat.format(time);
    }

    public static String getHourOfDay() {
        SimpleDateFormat simple = new SimpleDateFormat("HH");
        return simple.format(Calendar.getInstance().getTime());
    }


    public static String getBigMonth(int diff) {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, diff);
        int month = cal.get(Calendar.MONTH) + 1;
        StringBuilder sb = new StringBuilder();
        if (month <= 10) {
            sb.append(upper[month]);
        } else {
            sb.append("十").append(upper[month % 10]);
        }
        sb.append("月");//拼接月
        return sb.toString();
    }

    public static int getWeekDay(int diff) {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, diff);
        int weekday = cal.get(Calendar.DAY_OF_WEEK);
        weekday = (weekday + 6) % 7;
        weekday = weekday == 0 ? 7 : weekday;
        return weekday;
    }

    public static String getBigWeekDay(int diff) {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, diff);
        int weekday = cal.get(Calendar.DAY_OF_WEEK);
        weekday = (weekday + 6) % 7;
        weekday = weekday == 0 ? 7 : weekday;
        StringBuilder sb = new StringBuilder();
        if (weekday == 7) {
            sb.append("星期天");
        } else {
            sb.append("星期").append(upper[weekday]);
        }
        return sb.toString();
    }

    public static String getHour() {
        Calendar calendar = Calendar.getInstance();
        return calendar.HOUR + "";
    }

    /**
     * 距离今天多久
     *
     * @param date
     * @return
     */
    public static String fromToday(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        long time = date.getTime() / 1000;
        long now = new Date().getTime() / 1000;
        long ago = now - time;
        if (ago <= ONE_HOUR)
            return ago / ONE_MINUTE + "分钟前";
        else if (ago <= ONE_DAY)
            return ago / ONE_HOUR + "小时" + (ago % ONE_HOUR / ONE_MINUTE)
                    + "分钟前";
        else if (ago <= ONE_DAY * 2)
            return "昨天" + calendar.get(Calendar.HOUR_OF_DAY) + "点"
                    + calendar.get(Calendar.MINUTE) + "分";
        else if (ago <= ONE_DAY * 3)
            return "前天" + calendar.get(Calendar.HOUR_OF_DAY) + "点"
                    + calendar.get(Calendar.MINUTE) + "分";
        else if (ago <= ONE_MONTH) {
            long day = ago / ONE_DAY;
            return day + "天前" + calendar.get(Calendar.HOUR_OF_DAY) + "点"
                    + calendar.get(Calendar.MINUTE) + "分";
        } else if (ago <= ONE_YEAR) {
            long month = ago / ONE_MONTH;
            long day = ago % ONE_MONTH / ONE_DAY;
            return month + "个月" + day + "天前"
                    + calendar.get(Calendar.HOUR_OF_DAY) + "点"
                    + calendar.get(Calendar.MINUTE) + "分";
        } else {
            long year = ago / ONE_YEAR;
            int month = calendar.get(Calendar.MONTH) + 1;// JANUARY which is 0 so month+1
            return year + "年前" + month + "月" + calendar.get(Calendar.DATE)
                    + "日";
        }

    }

    /**
     * 距离截止日期还有多长时间
     *
     * @param date
     * @return
     */
    public static String fromDeadline(Date date) {
        long deadline = date.getTime() / 1000;
        long now = (new Date().getTime()) / 1000;
        long remain = deadline - now;
        if (remain <= ONE_HOUR)
            return "只剩下" + remain / ONE_MINUTE + "分钟";
        else if (remain <= ONE_DAY)
            return "只剩下" + remain / ONE_HOUR + "小时"
                    + (remain % ONE_HOUR / ONE_MINUTE) + "分钟";
        else {
            long day = remain / ONE_DAY;
            long hour = remain % ONE_DAY / ONE_HOUR;
            long minute = remain % ONE_DAY % ONE_HOUR / ONE_MINUTE;
            return "只剩下" + day + "天" + hour + "小时" + minute + "分钟";
        }

    }

    /**
     * 距离今天的绝对时间
     *
     * @param date
     * @return
     */
    public static String toToday(Date date) {
        long time = date.getTime() / 1000;
        long now = (new Date().getTime()) / 1000;
        long ago = now - time;
        if (ago <= ONE_HOUR)
            return ago / ONE_MINUTE + "分钟";
        else if (ago <= ONE_DAY)
            return ago / ONE_HOUR + "小时" + (ago % ONE_HOUR / ONE_MINUTE) + "分钟";
        else if (ago <= ONE_DAY * 2)
            return "昨天" + (ago - ONE_DAY) / ONE_HOUR + "点" + (ago - ONE_DAY)
                    % ONE_HOUR / ONE_MINUTE + "分";
        else if (ago <= ONE_DAY * 3) {
            long hour = ago - ONE_DAY * 2;
            return "前天" + hour / ONE_HOUR + "点" + hour % ONE_HOUR / ONE_MINUTE
                    + "分";
        } else if (ago <= ONE_MONTH) {
            long day = ago / ONE_DAY;
            long hour = ago % ONE_DAY / ONE_HOUR;
            long minute = ago % ONE_DAY % ONE_HOUR / ONE_MINUTE;
            return day + "天前" + hour + "点" + minute + "分";
        } else if (ago <= ONE_YEAR) {
            long month = ago / ONE_MONTH;
            long day = ago % ONE_MONTH / ONE_DAY;
            long hour = ago % ONE_MONTH % ONE_DAY / ONE_HOUR;
            long minute = ago % ONE_MONTH % ONE_DAY % ONE_HOUR / ONE_MINUTE;
            return month + "个月" + day + "天" + hour + "点" + minute + "分前";
        } else {
            long year = ago / ONE_YEAR;
            long month = ago % ONE_YEAR / ONE_MONTH;
            long day = ago % ONE_YEAR % ONE_MONTH / ONE_DAY;
            return year + "年前" + month + "月" + day + "天";
        }

    }

    public static String getYear() {
        return Calendar.getInstance().get(Calendar.YEAR) + "";
    }

    public static String getMonth() {
        int month = Calendar.getInstance().get(Calendar.MONTH) + 1;
        return month + "";
    }

    public static String getDay() {
        return Calendar.getInstance().get(Calendar.DATE) + "";
    }

    public static String getDay(int diff) {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, diff);
        return cal.get(Calendar.DATE) + "";
    }

    public static String get24Hour() {
        return Calendar.getInstance().get(Calendar.HOUR_OF_DAY) + "";
    }

    public static String getMinute() {
        return Calendar.getInstance().get(Calendar.MINUTE) + "";
    }

    public static String getSecond() {
        return Calendar.getInstance().get(Calendar.SECOND) + "";
    }

    /**
     * 日期加或减num天
     *
     * @param sDate
     * @return num
     * @author mdq
     * @date 2020/8/5 14:40
     */
    public static Date getDateByDay(Date sDate, int num) {
        Calendar cal = Calendar.getInstance();
        // 设置开始时间
        cal.setTime(sDate);
        //增加或减少num天
        cal.add(Calendar.DATE, num);
        return cal.getTime();
    }

    public static String formatToYM(Date date) {
        SimpleDateFormat format = new SimpleDateFormat(DATE_PATTERN_NUM_YM);
        String str = format.format(date);
        return str;
    }

    public static String parseToYM(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_PATTERN_YM);
        return sdf.format(date);
    }

    public static Date StrToDate(String str) {
        SimpleDateFormat format = new SimpleDateFormat(DATE_PATTERN);
        Date date = null;
        try {
            date = format.parse(str);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    public static Date StrToDateTime(String str) {
        SimpleDateFormat format = new SimpleDateFormat(DATE_TIME_PATTERN);
        Date date = null;
        try {
            date = format.parse(str);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    /**
     * 根据日期来判断属于第几季度
     *
     * @param date
     * @return quarter （202101）
     * @author wujianfan
     * @date 2021/11/22 17:25
     */
    public static String getQuarterByDate(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        //设置季度日期分界线
        Date quarter1 = stringToDate(cal.get(Calendar.YEAR) + "-3-31 23:59:59",DATE_TIME_PATTERN);
        Date quarter2 = stringToDate(cal.get(Calendar.YEAR) + "-6-30 23:59:59",DATE_TIME_PATTERN);
        Date quarter3 = stringToDate(cal.get(Calendar.YEAR) + "-9-30 23:59:59",DATE_TIME_PATTERN);
        Date quarter4 = stringToDate(cal.get(Calendar.YEAR) + "-12-31 23:59:59",DATE_TIME_PATTERN);
        if(date.before(quarter1)) return cal.get(Calendar.YEAR) + "01";
        if(date.after(quarter1) && date.before(quarter2)) return cal.get(Calendar.YEAR) + "02";
        if(date.after(quarter2) && date.before(quarter3)) return cal.get(Calendar.YEAR) + "03";
        if(date.after(quarter3) && date.before(quarter4)) return cal.get(Calendar.YEAR) + "04";
        return null;
    }

    /**
     * 根据日期来获取上一季度
     *
     * @param date
     * @return quarter（202101）
     * @author wujianfan
     * @date 2021/11/22 17:25
     */
    public static String getPastQuarterByDate(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        //设置季度日期分界线
        Date quarter1 = stringToDate(cal.get(Calendar.YEAR) + "-3-31 23:59:59",DATE_TIME_PATTERN);
        Date quarter2 = stringToDate(cal.get(Calendar.YEAR) + "-6-30 23:59:59",DATE_TIME_PATTERN);
        Date quarter3 = stringToDate(cal.get(Calendar.YEAR) + "-9-30 23:59:59",DATE_TIME_PATTERN);
        Date quarter4 = stringToDate(cal.get(Calendar.YEAR) + "-12-31 23:59:59",DATE_TIME_PATTERN);
        if(date.after(quarter1) && date.before(quarter2)) return cal.get(Calendar.YEAR) + "01";
        if(date.after(quarter2) && date.before(quarter3)) return cal.get(Calendar.YEAR) + "02";
        if(date.after(quarter3) && date.before(quarter4)) return cal.get(Calendar.YEAR) + "03";
        if(date.before(quarter1)) {
            //当前时间为第一季度，则上一季度为上一年的第四季度
            cal.add(1,-1); // 年份减一
            return cal.get(Calendar.YEAR) + "04";
        }
        return null;
    }
}
